package com.unlcn.ils.wms.backend.service.inspectApp.impl;

import cn.huiyunche.commons.constant.QiniuConstant;
import cn.huiyunche.commons.exception.BusinessException;
import cn.huiyunche.commons.utils.QiniuUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.unlcn.ils.wms.backend.bo.inspectAppBO.TmsInboundInspectBO;
import com.unlcn.ils.wms.backend.bo.inspectAppBO.TmsInspectExcpAttachBO;
import com.unlcn.ils.wms.backend.bo.inspectAppBO.TmsInspectExcpDetailBO;
import com.unlcn.ils.wms.backend.enums.*;
import com.unlcn.ils.wms.backend.enums.excp.ExcpStatusEnum;
import com.unlcn.ils.wms.backend.service.inspectApp.*;
import com.unlcn.ils.wms.backend.util.jpush.JpushClientUtils;
import com.unlcn.ils.wms.base.dto.*;
import com.unlcn.ils.wms.base.mapper.inbound.WmsInboundOrderDetailMapper;
import com.unlcn.ils.wms.base.mapper.inbound.WmsInboundOrderMapper;
import com.unlcn.ils.wms.base.mapper.inbound.WmsInboundRepairMapper;
import com.unlcn.ils.wms.base.mapper.inspectApp.*;
import com.unlcn.ils.wms.base.mapper.junmadcs.WmsOutOfStorageMapper;
import com.unlcn.ils.wms.base.mapper.outbound.WmsOutboundTaskMapper;
import com.unlcn.ils.wms.base.mapper.outbound.WmsPreparationVehicleDetailMapper;
import com.unlcn.ils.wms.base.mapper.stock.WmsInventoryLocationMapper;
import com.unlcn.ils.wms.base.mapper.stock.WmsInventoryMapper;
import com.unlcn.ils.wms.base.mapper.sys.SysUserMapper;
import com.unlcn.ils.wms.base.model.inbound.*;
import com.unlcn.ils.wms.base.model.inspectApp.*;
import com.unlcn.ils.wms.base.model.junmadcs.WmsOutOfStorage;
import com.unlcn.ils.wms.base.model.outbound.WmsOutboundTask;
import com.unlcn.ils.wms.base.model.outbound.WmsPreparationVehicleDetail;
import com.unlcn.ils.wms.base.model.outbound.WmsPreparationVehicleDetailExample;
import com.unlcn.ils.wms.base.model.stock.WmsInventory;
import com.unlcn.ils.wms.base.model.stock.WmsInventoryLocation;
import com.unlcn.ils.wms.base.model.stock.WmsInventoryLocationExample;
import com.unlcn.ils.wms.base.model.sys.SysUser;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 维修再验车的业务
 */
@Service
public class WmsRepairInspectServiceImpl implements WmsRepairInspectService {

    private Logger logger = LoggerFactory.getLogger(WmsRepairInspectServiceImpl.class);

    @Autowired
    private WmsInboundRepairMapper wmsInboundRepairMapper;
    @Autowired
    private TmsInspectExcpMapper tmsInspectExcpMapper;
    @Autowired
    private TmsOutboundInspectExcpMapper tmsOutboundInspectExcpMapper;
    @Autowired
    private WmsOutboundTaskMapper wmsOutboundTaskMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private WmsInboundOrderDetailMapper wmsInboundOrderDetailMapper;
    @Autowired
    private WmsInboundOrderMapper wmsInboundOrderMapper;
    @Autowired
    private WmsInventoryLocationMapper wmsInventoryLocationMapper;
    @Autowired
    private WmsInventoryMapper wmsInventoryMapper;
    @Autowired
    private WmsOutOfStorageMapper wmsOutOfStorageMapper;
    @Autowired
    private WmsPreparationVehicleDetailMapper wmsPreparationVehicleDetailMapper;
    @Autowired
    private TmsInspectComponentMissMapper tmsInspectComponentMissMapper;
    @Autowired
    private TmsInspectExcpTypeMapper tmsInspectExcpTypeMapper;
    @Autowired
    private TmsOutboundComponentMissMapper tmsOutboundComponentMissMapper;
    @Autowired
    private TmsInspectExcpExpandMapper tmsInspectExcpExpandMapper;
    @Autowired
    private TmsInspectExcpAttachsMapper tmsInspectExcpAttachsMapper;
    @Autowired
    private WmsOutboundExcpExpandMapper wmsOutboundExcpExpandMapper;
    @Autowired
    private TmsOutboundExcpAttachsMapper tmsOutboundExcpAttachsMapper;
    @Autowired
    private TmsInspectExcpService tmsInspectExcpService;
    @Autowired
    private TmsInspectComponentMissService tmsInspectComponentMissService;
    @Autowired
    private WmsOutboundInspectExcpService wmsOutboundInspectExcpService;
    @Autowired
    private WmsOutboundComponentMissService wmsOutboundComponentMissService;


    private static final String TYPE_MOVECAR = "1001";//待移车列表推送类别

    /**
     * 获取维修单信息
     */
    @Override
    public TmsInboundInspectBO getRepairInfo(WmsRepairInspectDTO dto) throws Exception {

        logger.info("WmsRepairInspectServiceImpl.getRepairInfo param vin:{}.", dto);
        if (Objects.equals(dto, null)) {
            throw new BusinessException("输入信息不能为空");
        }
        if (StringUtils.isBlank(dto.getWhCode())) {
            throw new BusinessException("仓库编码不能为空");
        }
        if (StringUtils.isBlank(dto.getVin())) {
            throw new BusinessException("车架号不能为空");
        }
        String vin = dto.getVin();
        String whCode = dto.getWhCode();
        WmsInboundRepairExample repairExample = new WmsInboundRepairExample();
        WmsInboundRepairExample.Criteria rpCriteria = repairExample.createCriteria()
                .andRpStatusNotEqualTo(String.valueOf(WmsRepairStatusEnum.WMS_REPAIR_STATUS_COMPLETE.getValue()))
                .andIsDeletedNotEqualTo(DeleteFlagEnum.DELETED.getValue());
        if (vin.trim().length() == 17) {
            rpCriteria.andRpVinEqualTo(vin);
        } else {
            rpCriteria.andRpWaybillNoEqualTo(vin);
        }
        List<WmsInboundRepair> wmsInboundRepairs = wmsInboundRepairMapper.selectByExample(repairExample);
        //构造返回结果
        TmsInboundInspectBO rpReturnBo = new TmsInboundInspectBO();
        if (CollectionUtils.isEmpty(wmsInboundRepairs))
            throw new BusinessException("未查询到该车架号的维修信息!");

        //返回值--设置车架号  维修单id
        WmsInboundRepair repair = wmsInboundRepairs.get(0);
        if (StringUtils.isNotBlank(repair.getRpWhCode()) && !(whCode.equals(repair.getRpWhCode()))) {
            throw new BusinessException("该用户不具有该仓库的操作权限");
        }
        if (WmsInboundRepairStatusEnum.NOT_DEAL.getCode().equals(repair.getRpStatus()))
            throw new BusinessException("该维修车辆还未提交维修");
        //校验是否维修出库
        if (StringUtils.isNotBlank(repair.getRpType())
                && String.valueOf(WmsRepairTypeEnum.WMS_REPAIR_TYPE_OUTBOUND.getValue()).equals(repair.getRpType())) {
            if (StringUtils.isBlank(repair.getRpInOutStatus())
                    || (StringUtils.isNotBlank(repair.getRpInOutStatus()) && RepairInOutStatusEnum.NO_SEND.getCode().equals(repair.getRpInOutStatus())))
                throw new BusinessException("该车架号还未维修出库处理,请到出库确认界面扫描维修单号出库操作!");
        }

        if (WmsInboundRepairStatusEnum.DEALED.getCode().equals(repair.getRpStatus())) {
            if (StringUtils.isNotBlank(repair.getRepairInspectPlace())
                    && String.valueOf(WmsRepairInspectPlaceEnum.INBOUND_PLACE.getValue()).equals(repair.getRepairInspectPlace()))
                throw new BusinessException("该车辆已经验车合格,请进行移车申请扫码!");
            if (StringUtils.isNotBlank(repair.getRepairInspectPlace())
                    && String.valueOf(WmsRepairInspectPlaceEnum.PREPAIR_PLACE.getValue()).equals(repair.getRepairInspectPlace()))
                throw new BusinessException("该车辆已经验车合格,到备料区进行出库");
        }
        rpReturnBo.setVin(repair.getRpVin());
        rpReturnBo.setStyle(repair.getRpVehicleSpecName());
        rpReturnBo.setStyleDesc(repair.getRpVehicleSpecName());
        rpReturnBo.setRpId(String.valueOf(repair.getRpId()));
        rpReturnBo.setId(StringUtils.isNotBlank(repair.getRpOdId()) ? Long.valueOf(repair.getRpOdId()) : null);
        rpReturnBo.setStyle(repair.getRpVehicleSpecName());//车型
        String rpInAndOutType = repair.getRpInandoutType();
        rpReturnBo.setRpInAndOutType(rpInAndOutType);
        rpReturnBo.setInspectStatusValue(TmsInspectStatusEnum.WAYBILL_REPAIRING.getValue());//维修状态
        rpReturnBo.setInspectStatusText(TmsInspectStatusEnum.WAYBILL_REPAIRING.getText());//维修中
        //对应的入库和出库维修类型 --关联查询对应的出库任务id关联对应的异常信息展示
        //判断维修的类型--去对应的入库和出库单关联查询对应的异常回显
        if ((StringUtils.isNotBlank(rpInAndOutType)
                && String.valueOf(WmsRepairInAndOutTypeEnum.INBOUND_REPAIR.getValue()).equals(rpInAndOutType))) {
            List<TmsInspectExcpDTO> positionCountList = tmsInspectExcpService.getPositionExcpCountByInspectId(rpReturnBo.getId(), whCode);
            rpReturnBo.setPositionAndExcpCount(positionCountList);
            String missComponentNames = tmsInspectComponentMissService.getMissComponentNamesNew(rpReturnBo.getId(), whCode);
            rpReturnBo.setMissComponentNames(missComponentNames);
        }
        //出库维修但实际入库验车的车辆信息回显
        if ((StringUtils.isNotBlank(rpInAndOutType)
                && String.valueOf(WmsRepairInAndOutTypeEnum.OUTBOUND_REPAIR.getValue()).equals(rpInAndOutType))) {
            List<WmsOutboundInspectExcpDTO> byInspectId = wmsOutboundInspectExcpService.getPositionExcpCountByInspectId(rpReturnBo.getId(), whCode);
            ArrayList<TmsInspectExcpDTO> excpDTOS = Lists.newArrayList();
            byInspectId.forEach((WmsOutboundInspectExcpDTO v) -> {
                TmsInspectExcpDTO excpDTO = new TmsInspectExcpDTO();
                BeanUtils.copyProperties(v, excpDTO);
                excpDTOS.add(excpDTO);
            });
            rpReturnBo.setPositionAndExcpCount(excpDTOS);
            String namesNew = wmsOutboundComponentMissService.getMissComponentNamesNew(rpReturnBo.getId(), whCode);
            rpReturnBo.setMissComponentNames(namesNew);
        }

        return rpReturnBo;
    }


    /**
     * 维修根据异常位置查询到异常信息
     */
    @Override
    public List<TmsInspectExcpDetailBO> getExcpInfoByPositionId(WmsRepairInspectDTO dto) {
        logger.info("WmsRepairInspectServiceImpl.getRepairInspectPlace param{}", dto);
        if (Objects.equals(dto, null))
            throw new BusinessException("传入参数为空!");
        if (StringUtils.isBlank(dto.getRpId()))
            throw new BusinessException("传入的维修单id不能为空");
        if (StringUtils.isBlank(dto.getPositionId()))
            throw new BusinessException("传入的区域id不能为空");
        String inboundRepair = String.valueOf(WmsRepairInAndOutTypeEnum.INBOUND_REPAIR.getValue());
        String outboundRepair = String.valueOf(WmsRepairInAndOutTypeEnum.OUTBOUND_REPAIR.getValue());
        //判断是否是维修单
        WmsInboundRepair repair = wmsInboundRepairMapper.selectByPrimaryKey(Long.valueOf(dto.getRpId()));
        if (Objects.equals(repair, null))
            throw new BusinessException("未查询到id为" + dto.getRpId() + "的维修单信息");
        //如果是入库维修
        List<TmsInspectExcpDetailBO> result_list = new ArrayList<>();
        if (inboundRepair.equals(repair.getRpInandoutType())) {
            //获取对应区域异常列表
            //过滤已经已经处理关闭的异常
            HashMap<String, Object> params = Maps.newHashMap();
            params.put("inspectId", repair.getRpOdId());
            params.put("positionId", dto.getPositionId());
            params.put("closeValue", WmsExcpStatusEnum.CLOSED_EXCP.getValue());
            params.put("notDel", DeleteFlagEnum.NORMAL.getValue());
            List<TmsInspectExcpDTO> excpDTOList = tmsInspectExcpExpandMapper.selectExcpListByPositionId(params);
            if (CollectionUtils.isNotEmpty(excpDTOList)) {
                for (TmsInspectExcpDTO excpDTO : excpDTOList) {
                    //转换对象
                    TmsInspectExcpDetailBO detailBO = new TmsInspectExcpDetailBO();
                    BeanUtils.copyProperties(excpDTO, detailBO);
                    //获取图片的地址
                    TmsInspectExcpAttachsExample attachsExample = new TmsInspectExcpAttachsExample();
                    TmsInspectExcpAttachsExample.Criteria criteria = attachsExample.createCriteria();
                    criteria.andExcpIdEqualTo(excpDTO.getExcpId());
                    criteria.andDelFlagNotEqualTo(false);
                    List<TmsInspectExcpAttachs> attachsList = tmsInspectExcpAttachsMapper.selectByExample(attachsExample);
                    if (CollectionUtils.isNotEmpty(attachsList)) {
                        List<TmsInspectExcpAttachBO> attachBOList = new ArrayList<>();
                        for (TmsInspectExcpAttachs attachs : attachsList) {
                            TmsInspectExcpAttachBO attachBO = new TmsInspectExcpAttachBO();
                            attachBO.setPicUrl(QiniuUtil.generateDownloadURL(QiniuConstant.QINIU_DOWNLOAD_ADDRESS, attachs.getPicKey(), "", null, null));
                            attachBO.setId(attachs.getId());
                            attachBO.setPicKey(attachs.getPicKey());
                            attachBOList.add(attachBO);
                        }
                        detailBO.setAttachBOS(attachBOList);
                    }
                    result_list.add(detailBO);
                }
            }
        }
        //如果是出库维修
        if (outboundRepair.equals(repair.getRpInandoutType())) {
            //获取对应区域异常列表
            HashMap<String, Object> params = Maps.newHashMap();
            params.put("inspectId", repair.getRpOdId());
            params.put("positionId", dto.getPositionId());
            params.put("notDel", DeleteFlagEnum.NORMAL.getValue());
            params.put("closeValue", ExcpStatusEnum.CLOSED.getCode());
            List<WmsOutboundInspectExcpDTO> excpDTOList = wmsOutboundExcpExpandMapper.selectExcpListByPositionId(params);
            if (CollectionUtils.isNotEmpty(excpDTOList)) {
                for (WmsOutboundInspectExcpDTO excpDTO : excpDTOList) {
                    //转换对象
                    TmsInspectExcpDetailBO detailBO = new TmsInspectExcpDetailBO();
                    BeanUtils.copyProperties(excpDTO, detailBO);
                    //获取图片的地址
                    TmsOutboundExcpAttachsExample attachsExample = new TmsOutboundExcpAttachsExample();
                    TmsOutboundExcpAttachsExample.Criteria criteria = attachsExample.createCriteria();
                    criteria.andExcpIdEqualTo(excpDTO.getExcpId());
                    criteria.andDelFlagNotEqualTo(false);
                    List<TmsOutboundExcpAttachs> attachsList = tmsOutboundExcpAttachsMapper.selectByExample(attachsExample);
                    if (CollectionUtils.isNotEmpty(attachsList)) {
                        List<TmsInspectExcpAttachBO> attachBOList = new ArrayList<>();
                        for (TmsOutboundExcpAttachs attachs : attachsList) {
                            TmsInspectExcpAttachBO attachBO = new TmsInspectExcpAttachBO();
                            attachBO.setPicUrl(QiniuUtil.generateDownloadURL(QiniuConstant.QINIU_DOWNLOAD_ADDRESS, attachs.getPicKey(), "", null, null));
                            attachBO.setPicKey(attachs.getPicKey());
                            attachBO.setId(attachs.getId());
                            attachBOList.add(attachBO);
                        }
                        detailBO.setAttachBOS(attachBOList);
                    }
                    result_list.add(detailBO);
                }
            }
        }
        return result_list;
    }

    /**
     * 获取维修单缺件信息
     */
    @Override
    public List<TmsInspectComponentMissDTO> getRpComponentMissInfo(WmsRepairInspectDTO dto) throws Exception {
        logger.info("WmsRepairInspectServiceImpl.getRpComponentMissInfo param{}", dto);
        if (Objects.equals(dto, null))
            throw new BusinessException("传入参数为空!");
        if (StringUtils.isBlank(dto.getWhCode()))
            throw new BusinessException("传入仓库code为空!");
        if (StringUtils.isBlank(dto.getRpId()))
            throw new BusinessException("传入的维修单id不能为空");
        String inboundRepair = String.valueOf(WmsRepairInAndOutTypeEnum.INBOUND_REPAIR.getValue());
        String outboundRepair = String.valueOf(WmsRepairInAndOutTypeEnum.OUTBOUND_REPAIR.getValue());
        //判断是否是维修单
        WmsInboundRepair repair = wmsInboundRepairMapper.selectByPrimaryKey(Long.valueOf(dto.getRpId()));
        if (Objects.equals(repair, null))
            throw new BusinessException("未查询到id为" + dto.getRpId() + "的维修单信息");
        //如果是入库维修
        //判断什么类型的维修
        List<TmsInspectComponentMissDTO> componentMissList = Lists.newArrayList();
        if (StringUtils.isNotBlank(repair.getRpInandoutType())
                && inboundRepair.equals(repair.getRpInandoutType())) {
            //关联入库缺件
            componentMissList = tmsInspectComponentMissService.getComponentMissListNew(dto.getVin(),
                    dto.getWhCode());
        }
        if (StringUtils.isNotBlank(repair.getRpInandoutType())
                && outboundRepair.equals(repair.getRpInandoutType())) {
            //关联出库缺件
            componentMissList = wmsOutboundComponentMissService.getComponentMissList(repair.getRpVin(), dto.getWhCode());
        }
        return componentMissList;
    }


    /**
     * 维修合格
     */
    @Override
    public void updateRepairPass(WmsRepairInspectDTO dto) throws Exception {
        logger.info("WmsRepairInspectServiceImpl.updateRepairPass param{}", dto);
        if (Objects.equals(dto, null))
            throw new BusinessException("传入参数为空!");
        if (StringUtils.isBlank(dto.getRpId()))
            throw new BusinessException("传入维修单Id为空");
        if (StringUtils.isBlank(dto.getUserId()))
            throw new BusinessException("传入的用户id为空");
        if (StringUtils.isBlank(dto.getWhCode()))
            throw new BusinessException("传入的仓库code为空");
        if ((WhCodeEnum.JM_XY.getValue().equals(dto.getWhCode())
                || WhCodeEnum.JM_CS.getValue().equals(dto.getWhCode()))
                && StringUtils.isBlank(dto.getExcpInpsectPlace()))
            throw new BusinessException("维修不合格选择的验车地点不能为空!");
        //重庆库入库区检查维修不合格--需要后台默认
        if (WhCodeEnum.UNLCN_XN_CQ.getValue().equals(dto.getWhCode()))
            dto.setExcpInpsectPlace(String.valueOf(WmsRepairInspectPlaceEnum.INBOUND_PLACE.getValue()));
        String initValue = String.valueOf(WmsRepairStatusEnum.WMS_REPAIR_STATUS_NOT_HANDLE.getValue());
        String finishValue = String.valueOf(WmsRepairStatusEnum.WMS_REPAIR_STATUS_COMPLETE.getValue());
        //查询对应的维修单
        WmsInboundRepair repair = wmsInboundRepairMapper.selectByPrimaryKey(Long.valueOf(dto.getRpId()));
        if (Objects.equals(repair, null))
            throw new BusinessException("未查询到id为" + dto.getRpId() + "的维修单信息");
        if (initValue.equals(repair.getRpStatus()))
            throw new BusinessException("该维修单还未提交维修");
        if (finishValue.equals(repair.getRpStatus()))
            throw new BusinessException("该维修单已经进行过该操作,无需重复提交");

        SysUser sysUser = sysUserMapper.selectByPrimaryKey(Integer.valueOf(dto.getUserId()));
        if (Objects.equals(sysUser, null))
            throw new BusinessException("未查询到id为:" + dto.getUserId() + "的用户信息");
        //判断维修的类型是入库维修还是出库维修
        String outboundRepairValue = String.valueOf(WmsRepairInAndOutTypeEnum.OUTBOUND_REPAIR.getValue());
        String inboundRepairValue = String.valueOf(WmsRepairInAndOutTypeEnum.INBOUND_REPAIR.getValue());
        String preparePlace = String.valueOf(WmsRepairInspectPlaceEnum.PREPAIR_PLACE.getValue());
        String inboundPlace = String.valueOf(WmsRepairInspectPlaceEnum.INBOUND_PLACE.getValue());
        //说明：
        //点击维修合格相关联的异常和缺件异常都会逻辑删除
        //君马入库的异常不会进行入库操作。不会有order记录
        //君马出库维修完成时间大于两个小时  或者再验车不合格选择了到入库去验车的维修--入库区验车
        //重庆库异常入库 然后在出库维修  只能到入库区验车
        //入库区的验车维修合格都需要同步记录到order
        //君马再选择到备料出库区验车的记录 需要关联任务表数据
        //出库维修合格(开始没选择到入库区验车维修检验合格选择到入库区验车)--清库存 写数据到接口表  更新状态

        //逻辑删除对应的关联异常信息
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (StringUtils.isNotBlank(repair.getRpInandoutType())
                && inboundRepairValue.equals(repair.getRpInandoutType())) {
            //入库维修--更新关联的异常为逻辑删除
            TmsInspectExcp excp = new TmsInspectExcp();
            excp.setDelFlag(false);
            excp.setGmtUpdate(date);
            TmsInspectExcpExample excpExample = new TmsInspectExcpExample();
            excpExample.createCriteria().andDelFlagEqualTo(true)
                    .andInspectIdEqualTo(Long.valueOf(repair.getRpOdId()));
            tmsInspectExcpMapper.updateByExampleSelective(excp, excpExample);
            //更新关联的缺件异常逻辑删除
            TmsInspectComponentMiss componentMiss = new TmsInspectComponentMiss();
            componentMiss.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
            componentMiss.setGmtUpdate(date);
            TmsInspectComponentMissExample missExample = new TmsInspectComponentMissExample();
            missExample.createCriteria().andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue())
                    .andInspectIdEqualTo(Long.valueOf(repair.getRpOdId()));
            tmsInspectComponentMissMapper.updateByExampleSelective(componentMiss, missExample);
        }

        if (StringUtils.isNotBlank(repair.getRpInandoutType())
                && outboundRepairValue.equals(repair.getRpInandoutType())) {
            //出库维修--更新关联的异常为逻辑删除
            TmsOutboundInspectExcp inspectExcp = new TmsOutboundInspectExcp();
            inspectExcp.setDelFlag(false);
            inspectExcp.setGmtUpdate(date);
            TmsOutboundInspectExcpExample excpExamp = new TmsOutboundInspectExcpExample();
            excpExamp.createCriteria().andDelFlagEqualTo(true)
                    .andInspectIdEqualTo(Long.valueOf(repair.getRpOdId()));
            tmsOutboundInspectExcpMapper.updateByExampleSelective(inspectExcp, excpExamp);
            TmsOutboundComponentMiss componentMiss = new TmsOutboundComponentMiss();
            componentMiss.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
            componentMiss.setGmtUpdate(date);
            TmsOutboundComponentMissExample missExample = new TmsOutboundComponentMissExample();
            missExample.createCriteria().andInspectIdEqualTo(Long.valueOf(repair.getRpOdId()))
                    .andInspectVinEqualTo(repair.getRpVin())
                    .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());
            tmsOutboundComponentMissMapper.updateByExampleSelective(componentMiss, missExample);
            //出库维修开始选择的是备料区验车,再验车不合格选择到入库区验车的情况--君马库业务
            if (WhCodeEnum.JM_CS.getValue().equals(repair.getRpWhCode())
                    || WhCodeEnum.JM_XY.getValue().equals(repair.getRpWhCode())) {
                //要看之前选的是到备料区验车才进行相应的逻辑处理
                //并且这次选择的是再到入库区验车
                if (StringUtils.isNotBlank(repair.getRepairInspectPlace())
                        && preparePlace.equals(repair.getRepairInspectPlace())
                        && inboundPlace.equals(dto.getExcpInpsectPlace())) {
                    updateInsertOutOfStorage(dto, inboundPlace, repair, sysUser, date);
                }
            }

            if (preparePlace.equals(repair.getRepairInspectPlace())) {
                //备料区验车，维修出库的时候未释放库存只需要更新对应的任务为待验车
                //更新出库任务的状态为验车合格
                WmsOutboundTask outboundTask = wmsOutboundTaskMapper.selectByPrimaryKey(Long.valueOf(repair.getRpOdId()));
                outboundTask.setInspectTime(date);
                outboundTask.setInspectStatus(WmsOutboundInspectStatusEnum.WAYBILL_INIT.getValue());
                outboundTask.setModifyUserId(dto.getUserId());
                outboundTask.setModifyUserName(sysUser.getName());
                wmsOutboundTaskMapper.updateByPrimaryKeySelective(outboundTask);
            }
        }

        //入库类型的合格需要同步到order新的记录
        if (inboundPlace.equals(repair.getRepairInspectPlace())) {
            //入库区验车--需要同步数据到order表中  重新收货
            //维修查询最新的一次order同步记录到order表中
            WmsInboundOrder inboundOrder = new WmsInboundOrder();
            WmsInboundOrderDetail orderDetail = new WmsInboundOrderDetail();
            WmsInboundOrderDetailExample detailExample = new WmsInboundOrderDetailExample();
            detailExample.setOrderByClause("gmt_create desc");
            detailExample.setLimitStart(0);
            detailExample.setLimitEnd(1);
            detailExample.createCriteria().andOddVinEqualTo(repair.getRpVin());
            List<WmsInboundOrderDetail> wmsInboundOrderDetails = wmsInboundOrderDetailMapper.selectByExample(detailExample);
            if (CollectionUtils.isNotEmpty(wmsInboundOrderDetails)) {
                WmsInboundOrderDetail oldDetail = wmsInboundOrderDetails.get(0);
                BeanUtils.copyProperties(oldDetail, orderDetail);
                orderDetail.setOddId(null);

                WmsInboundOrder oldOrder = wmsInboundOrderMapper.selectByPrimaryKey(oldDetail.getOddOdId());
                BeanUtils.copyProperties(oldOrder, inboundOrder);
            }
            inboundOrder.setGmtCreate(new Date());
            inboundOrder.setGmtUpdate(new Date());
            inboundOrder.setIsDeleted(DeleteFlagEnum.NORMAL.getValue());
            inboundOrder.setOdWhCode(dto.getWhCode());
            WhCodeEnum whCodeEnum = WhCodeEnum.getByValue(dto.getWhCode());
            if (whCodeEnum != null) {
                inboundOrder.setOdWhName(whCodeEnum.getText());
            }
            inboundOrder.setInspectStatus(TmsInspectStatusEnum.WAYBILL_QUALIFY.getValue());//验车合格
            inboundOrder.setOdStatus(String.valueOf(WmsInboundStatusEnum.WMS_INBOUND_CREATE.getValue()));
            inboundOrder.setOdCheckResult(WmsCheckResultEnum.WAYBILL_QUALIFY.getText());
            inboundOrder.setOdCheckDesc(WmsCheckDescEnum.WAYBILL_QUALIFY.getText());
            inboundOrder.setCreateUserId(dto.getUserId());
            inboundOrder.setCreateUserName(sysUser.getName());
            inboundOrder.setModifyUserId(dto.getUserId());
            inboundOrder.setModifyUserName(sysUser.getName());
            inboundOrder.setInspectTime(date);
            inboundOrder.setOdInspectExcpType(null);
            //检查是存在
            wmsInboundOrderMapper.insertSelective(inboundOrder);
            //设置明细
            orderDetail.setOddOdId(inboundOrder.getOdId());
            orderDetail.setOddWhZoneCode(null);
            orderDetail.setOddWhZoneName(null);
            orderDetail.setOddWhLocCode(null);
            orderDetail.setOddWhLocName(null);
            orderDetail.setCreateUserId(dto.getUserId());
            orderDetail.setGmtCreate(date);
            orderDetail.setCreateUserId(dto.getUserId());
            orderDetail.setCreateUserName(sysUser.getName());
            orderDetail.setModifyUserId(dto.getUserId());
            orderDetail.setModifyUserName(sysUser.getName());
            orderDetail.setGmtUpdate(date);
            wmsInboundOrderDetailMapper.insertSelective(orderDetail);
            //君马库推送待移车信息到app
            updateSendListToAppForJm(dto, inboundOrder);
        }
        //修改维修单状态为维修完成 结果为维修合格
        repair.setRepairInspectPlace(dto.getExcpInpsectPlace());
        repair.setRpEndDate(sdf.format(date));//实际完成时间
        //计算维修耗时
        String rpStartDate = repair.getRpStartDate();
        long start = sdf.parse(rpStartDate).getTime();
        long end = date.getTime();
        long diff = end - start;
        //long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        long ns = 1000;
        //SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
        String take = diff / nh + "小时" + diff % nh / nm + "分" + diff % nh % nm / ns + "秒";
        repair.setRpTakeTime(take);//维修耗费时间
        repair.setRpStatus(String.valueOf(WmsRepairStatusEnum.WMS_REPAIR_STATUS_COMPLETE.getValue()));
        repair.setRpRepairResult(String.valueOf(WmsRepairResultEnum.REPAIR_PASS.getCode()));
        repair.setModifyUserId(dto.getUserId());
        repair.setModifyUserName(sysUser.getName());
        repair.setGmtUpdate(date);
        wmsInboundRepairMapper.updateByPrimaryKeySelective(repair);
    }

    /**
     * 同步推送通知到app--君马
     *
     * @param dto             参数封装
     * @param wmsInboundOrder 入库单
     */
    private void updateSendListToAppForJm(WmsRepairInspectDTO dto, WmsInboundOrder wmsInboundOrder) {
        //君马库进行通知推送
        if (StringUtils.isNotBlank(dto.getWhCode())) {
            if (WhCodeEnum.JM_CS.getValue().equals(dto.getWhCode()) ||
                    WhCodeEnum.JM_XY.getValue().equals(dto.getWhCode())) {
                //君马库需要推送可移车任务到app
                //只能是合格和缺件异常的车辆能够推送
                String excpTypeTypeCode = null;
                if (wmsInboundOrder.getOdInspectExcpType() != null) {
                    TmsInspectExcpType tmsInspectExcpType = tmsInspectExcpTypeMapper.selectByPrimaryKey(wmsInboundOrder.getOdInspectExcpType());
                    if (tmsInspectExcpType != null) {
                        excpTypeTypeCode = tmsInspectExcpType.getTypeCode();
                    }
                }
                if (TmsInspectStatusEnum.WAYBILL_QUALIFY.getValue() == wmsInboundOrder.getInspectStatus() ||
                        (StringUtils.isNotBlank(excpTypeTypeCode) && WmsInspectExcpTypeEnum.TYPE_MISS.getCode().equals(excpTypeTypeCode))) {

                    new Thread(() -> {
                        try {
                            String notiTile = "有新的待移车任务,请点击APP进行查收![中联物流]";
                            JpushClientUtils.sendToAllAndroidWithTag(notiTile, "", "", "", dto.getWhCode(), TYPE_MOVECAR);
                        } catch (Exception e) {
                            logger.error("updateSendListToAppForJm 推送消息失败 error:", e);
                        }
                    }).start();

                }
            }
        }
    }


    /**
     * 维修验车不合格
     *
     * @param dto 传输参数
     */
    @Override
    public void updateRepairExcp(WmsRepairInspectDTO dto) {
        logger.info("WmsRepairInspectServiceImpl.updateRepairExcp param{}", dto);
        if (Objects.equals(dto, null))
            throw new BusinessException("传入参数为空!");
        if (StringUtils.isBlank(dto.getRpId()))
            throw new BusinessException("传入维修单Id为空");
        if (StringUtils.isBlank(dto.getUserId()))
            throw new BusinessException("传入的用户id为空");
        if (StringUtils.isBlank(dto.getWhCode()))
            throw new BusinessException("传入的仓库code为空");
        if ((WhCodeEnum.JM_XY.getValue().equals(dto.getWhCode())
                || WhCodeEnum.JM_CS.getValue().equals(dto.getWhCode()))
                && StringUtils.isBlank(dto.getExcpInpsectPlace()))
            throw new BusinessException("维修不合格选择的验车地点不能为空!");
        //重庆库入库区检查维修不合格--需要后台默认
        if (WhCodeEnum.UNLCN_XN_CQ.getValue().equals(dto.getWhCode()))
            dto.setExcpInpsectPlace(String.valueOf(WmsRepairInspectPlaceEnum.INBOUND_PLACE.getValue()));
        String initValue = String.valueOf(WmsRepairStatusEnum.WMS_REPAIR_STATUS_NOT_HANDLE.getValue());
        String outboundRepairValue = String.valueOf(WmsRepairInAndOutTypeEnum.OUTBOUND_REPAIR.getValue());
        //String inboundRepairValue = String.valueOf(WmsRepairInAndOutTypeEnum.INBOUND_REPAIR.getValue());
        String prepareValue = String.valueOf(WmsRepairInspectPlaceEnum.PREPAIR_PLACE.getValue());
        String inboundPlace = String.valueOf(WmsRepairInspectPlaceEnum.INBOUND_PLACE.getValue());
        //查询对应的维修单
        WmsInboundRepair repair = wmsInboundRepairMapper.selectByPrimaryKey(Long.valueOf(dto.getRpId()));
        if (Objects.equals(repair, null))
            throw new BusinessException("未查询到id为" + dto.getRpId() + "的维修单信息");
        if (initValue.equals(repair.getRpStatus()))
            throw new BusinessException("该维修单还未提交维修");
        //开始选择了入库区验车  就不能再选择备料区验车
        if (inboundPlace.equals(repair.getRepairInspectPlace())
                && prepareValue.equals(dto.getExcpInpsectPlace()))
            throw new BusinessException("该维修单只能选择入库区再验车");
        if (!dto.getWhCode().equals(repair.getRpWhCode())) {
            throw new BusinessException("该用户不具有此仓库权限");
        }
        SysUser sysUser = sysUserMapper.selectByPrimaryKey(Integer.valueOf(dto.getUserId()));
        if (Objects.equals(sysUser, null))
            throw new BusinessException("未查询到id为:" + dto.getUserId() + "的用户信息");

        //判断维修的类型是入库维修还是出库维修
        //逻辑删除对应的关联异常信息
        Date date = new Date();
        //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //单纯的入库和出库维修验车不合格,因为不涉及到更新对应的order或者outboundtask
        //出库维修开始选择的是备料区验车,再验车不合格选择到入库区验车的情况--君马库业务
        if (WhCodeEnum.JM_CS.getValue().equals(repair.getRpWhCode())
                || WhCodeEnum.JM_XY.getValue().equals(repair.getRpWhCode())) {

            if (StringUtils.isNotBlank(repair.getRpInandoutType())
                    && outboundRepairValue.equals(repair.getRpInandoutType())) {
                //要看之前选的是到备料区验车才进行相应的逻辑处理
                //并且这次选择的是再到入库区验车
                if (StringUtils.isNotBlank(repair.getRepairInspectPlace())
                        && prepareValue.equals(repair.getRepairInspectPlace())
                        && inboundPlace.equals(dto.getExcpInpsectPlace())) {
                    updateInsertOutOfStorage(dto, inboundPlace, repair, sysUser, date);
                }
            }
        }
        //修改结果为维修不合格--不改变维修状态
        repair.setRepairInspectPlace(dto.getExcpInpsectPlace());
        repair.setRpRepairResult(String.valueOf(WmsRepairResultEnum.REPAIR_EXCP.getCode()));
        repair.setModifyUserId(dto.getUserId());
        repair.setModifyUserName(sysUser.getName());
        repair.setGmtUpdate(date);
        wmsInboundRepairMapper.updateByPrimaryKeySelective(repair);
    }

    /**
     * 针对初次选择备料区验车 再选择入库区验车业务  ---君马
     */
    private void updateInsertOutOfStorage(WmsRepairInspectDTO dto,
                                          String inboundPlace,
                                          WmsInboundRepair repair,
                                          SysUser sysUser,
                                          Date date) {
        //真的释放库存时侯,这个时候要更新任务状态为维修出库
        WmsOutboundTask outboundTask = new WmsOutboundTask();
        outboundTask.setOtId(Long.valueOf(repair.getRpOdId()));
        outboundTask.setOtType(OutBoundTaskTypeEnum.REPAIR_OUT.getCode());
        outboundTask.setGmtModify(new Date());
        outboundTask.setModifyUserId(dto.getUserId());
        outboundTask.setModifyUserName(sysUser.getName());
        wmsOutboundTaskMapper.updateByPrimaryKeySelective(outboundTask);
        //释放库存
        WmsInventoryLocationExample locationExample = new WmsInventoryLocationExample();
        locationExample.createCriteria().andInvlocVinEqualTo(repair.getRpVin())
                .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue())
                .andStatusEqualTo(InventoryLocationStatusEnum.REPAIR_LOCK_40.getCode());
        List<WmsInventoryLocation> wmsInventoryLocations = wmsInventoryLocationMapper.selectByExample(locationExample);
        if (CollectionUtils.isNotEmpty(wmsInventoryLocations)) {
            WmsInventoryLocation inventoryLocation = wmsInventoryLocations.get(0);
            inventoryLocation.setGmtUpdate(date);
            inventoryLocation.setModifyUserId(dto.getUserId());
            inventoryLocation.setModifyUserName(sysUser.getName());
            inventoryLocation.setStatus(InventoryLocationStatusEnum.MAINTAIN_LOCK_50.getCode());
            inventoryLocation.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
            wmsInventoryLocationMapper.updateByPrimaryKeySelective(inventoryLocation);
            WmsInventory inventory = new WmsInventory();
            inventory.setGmtUpdate(date);
            inventory.setModifyUserName(sysUser.getName());
            inventory.setModifyUserId(dto.getUserId());
            inventory.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
            inventory.setInvId(inventoryLocation.getInvlocInvId());
            wmsInventoryMapper.updateByPrimaryKeySelective(inventory);
            //更新维修单的验车地方,出库状态
            repair.setRepairInspectPlace(inboundPlace);
            repair.setRpInOutStatus(RepairInOutStatusEnum.HAVE_SEND.getCode());
            //写入数据到接口表
            WmsOutOfStorage wmsOutOfStorage = new WmsOutOfStorage();
            wmsOutOfStorage.setMatnr(repair.getRpMaterialCode());//物料编码
            wmsOutOfStorage.setZtype(InboundOrderBusinessTypeEnum.Z3.getCode());//业务类型
            //维修出库写入接口表
            wmsOutOfStorage.setSerialNo(repair.getRpRepairNo());//设置流水号
            wmsOutOfStorage.setSernr(repair.getRpVin());//车架号
            wmsOutOfStorage.setBldat(new Date());//出入库日期
            wmsOutOfStorage.setZaction(WmsOutOfStorageAction.ACTION_OUTBOUND.getValue());//动作
            //库存地点 - CS01-长沙 XY01-襄阳',
            if (WarehouseEnum.JM_XY.getWhCode().equals(dto.getWhCode())) {
                wmsOutOfStorage.setUmlgo("XY01");
            }
            if (WarehouseEnum.JM_CS.getWhCode().equals(dto.getWhCode())) {
                wmsOutOfStorage.setUmlgo("CS01");
            }
            wmsOutOfStorage.setSendStatus(SendStatusEnum.SEND_INIT.getValue());
            wmsOutOfStorage.setSendStatusSap(SendStatusEnum.SEND_INIT.getValue());
            wmsOutOfStorageMapper.insertSelective(wmsOutOfStorage);
        }
        //修改备料明细为已出库
        WmsPreparationVehicleDetail vehicleDetail = new WmsPreparationVehicleDetail();
        vehicleDetail.setGmtUpdate(new Date());
        vehicleDetail.setModifyUserName(sysUser.getName());
        vehicleDetail.setVdOutstockStatus(String.valueOf(WmsOutboundStatusEnum.WMS_OUTBOUND_FINISH.getValue()));
        vehicleDetail.setModifyUserName(sysUser.getName());
        WmsPreparationVehicleDetailExample detailExample = new WmsPreparationVehicleDetailExample();
        detailExample.createCriteria().andVdVinEqualTo(repair.getRpVin())
                .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue())
                .andVdOutstockStatusEqualTo(String.valueOf(WmsOutboundStatusEnum.WMS_OUTBOUND_NEW.getValue()));
        wmsPreparationVehicleDetailMapper.updateByExampleSelective(vehicleDetail, detailExample);

    }

    /**
     * 维修不合格时弹出的维修验车地址列表
     *
     * @param rpId 维修单id
     */
    @Override
    public ArrayList<WmsRepairInspectPlaceDTO> getRepairInspectPlace(String rpId) {
        logger.info("WmsRepairInspectServiceImpl.getRepairInspectPlace param{}", rpId);
        if (StringUtils.isBlank(rpId))
            throw new BusinessException("维修单Id不能为空!");
        String initValue = String.valueOf(WmsRepairStatusEnum.WMS_REPAIR_STATUS_NOT_HANDLE.getValue());
        String prepareValue = String.valueOf(WmsRepairInspectPlaceEnum.PREPAIR_PLACE.getValue());
        WmsInboundRepair repair = wmsInboundRepairMapper.selectByPrimaryKey(Long.valueOf(rpId));
        if (Objects.equals(repair, null))
            throw new BusinessException("未查询到id为" + rpId + "的维修单信息");
        if (initValue.equals(repair.getRpStatus())) {
            throw new BusinessException("该维修单还未提交维修");
        }
        ArrayList<WmsRepairInspectPlaceDTO> result = Lists.newArrayList();
        if (StringUtils.isNotBlank(repair.getRepairInspectPlace())
                && prepareValue.equals(repair.getRepairInspectPlace())) {
            //选择的备料区验车 可以再选择去备料区验车   但是选择了入库去验车就不能再选备料区验车了
            result.add(new WmsRepairInspectPlaceDTO(String.valueOf(WmsRepairInspectPlaceEnum.PREPAIR_PLACE.getValue()),
                    WmsRepairInspectPlaceEnum.PREPAIR_PLACE.getText()));
        }
        result.add(new WmsRepairInspectPlaceDTO(String.valueOf(WmsRepairInspectPlaceEnum.INBOUND_PLACE.getValue()),
                WmsRepairInspectPlaceEnum.INBOUND_PLACE.getText()));

        return result;
    }

}
